/**
 * g++ -o server_base server_base.cpp -lpthread
 * nohup ./server_base &
 */

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fstream>
#include <ctime>
#include <cstdlib>
#include <chrono>
#include <thread>
#include <pthread.h>

#define PORT 9999
#define MESSAGE_SIZE 1000
#define TOTAL_MESSAGES 2000
#define TOTAL_HOURS 24   
#define HEARTBEAT_MESSAGE "heartbeat"

// 生成随机间隔时间，范围是 0.1 到 60 分钟
double getRandomInterval(){
    return 0.1 + static_cast<double>(rand()) / RAND_MAX * (60.0 - 0.1);
}

// 获取当前时间字符串
std::string getCurrentTime(){
    time_t now = time(0);
    char buf[80];
    strftime(buf, sizeof(buf), "%Y-%m-%d %X", localtime(&now));
    return std::string(buf);
}

// 处理客户端连接的函数，每个客户端一个线程
void* handleClient(void* client_socket){
    int sock = *(int*)client_socket;
    delete (int*)client_socket;

    // 获取客户端的 IP 地址
    struct sockaddr_in addr;
    socklen_t addr_size = sizeof(struct sockaddr_in);
    getpeername(sock, (struct sockaddr*)&addr, &addr_size);
    char client_ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &addr.sin_addr, client_ip, INET_ADDRSTRLEN);

    // 记录客户端连接信息
    std::ofstream log_file("client_log.txt", std::ios::app);
    log_file << "Client connected: IP = " << client_ip << ", Time = " << getCurrentTime() << "\n";
    log_file.close();

    // 准备发送消息
    char message[MESSAGE_SIZE];
    memset(message, 'A', MESSAGE_SIZE - 1);
    message[MESSAGE_SIZE - 1] = '\0';

    // 开始发送消息，间隔随机，持续 1 小时或发送 2000 条信息
    auto start_time = std::chrono::system_clock::now();
    int message_sent = 0;
    while(message_sent < TOTAL_MESSAGES) {
        // 发送消息
        send(sock, message, MESSAGE_SIZE, 0);
        message_sent++;

        // 接收心跳包或其他消息
        char buffer[1024] = {0};
        int valread = recv(sock, buffer, sizeof(buffer), 0);
        if (valread > 0) {
            buffer[valread] = '\0';
            if (strcmp(buffer, HEARTBEAT_MESSAGE) == 0) {
                std::cout << "Received heartbeat from client: " << client_ip << "\n";
            } else {
                std::cout << "Received message from client: " << buffer << "\n";
            }
        }

        // 随机间隔时间
        double interval = getRandomInterval();
        std::this_thread::sleep_for(std::chrono::duration<double>(interval * 60));

        // 检查是否已经运行 1 小时
        auto elapsed_time = std::chrono::system_clock::now() - start_time;
        if(elapsed_time > std::chrono::hours(TOTAL_HOURS)){
            break;
        }

        // 增加调试信息输出
        std::cout << "Message sent to client. Total messages: " << message_sent << "\n";
    }

    std::cout << "发送完毕，停止连接。\n";
    close(sock);
    return nullptr;
}

int main(){
    int server_fd;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);

    // 创建套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0){
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 设置套接字选项
    if(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt failed");
        exit(EXIT_FAILURE);
    }

    // 绑定地址和端口
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    if(bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听连接
    if(listen(server_fd, 3) < 0){
        perror("listen failed");
        exit(EXIT_FAILURE);
    }

    std::cout << "Listening on port " << PORT << "...\n";

    // 主循环，处理多个客户端连接
    while(true){
        int* new_socket = new int;
        struct sockaddr_in client_address;
        socklen_t client_len = sizeof(client_address);

        // 接收客户端连接
        if((*new_socket = accept(server_fd, (struct sockaddr*)&client_address, &client_len)) < 0){
            perror("accept failed");
            delete new_socket;
            continue;
        }

        // 为每个客户端创建一个线程处理通信
        pthread_t client_thread;
        if(pthread_create(&client_thread, nullptr, handleClient, new_socket) != 0){
            perror("pthread_create failed");
            delete new_socket;
            continue;
        }

        // 分离线程，使其自动回收资源
        pthread_detach(client_thread);
    }

    // 关闭服务器套接字
    close(server_fd);

    return 0;
}